
#include "arcs_intersection.h"

//using namespace std;

double Arc::NormalizeAngle(double angle) {

    while (angle < 0)    angle += 2 * M_PI;
    while (angle >= 2 * M_PI) angle -= 2 * M_PI;

    return angle;
}

bool Arc::IsPointInArc(Point p) {
    double angle = atan2(p.y - center.y, p.x - center.x);
    angle = NormalizeAngle(angle);


    if (startangle <= endangle) {
        return angle >= startangle && angle <= endangle;
    }
    else {
        return angle >= startangle || angle <= endangle;
    }
}

bool Arc::CirclesArcIntersect(Point C1, double r1, Point C2, double r2, std::vector<Point>& intersections) {

    double dx = C2.x - C1.x;
    double dy = C2.y - C1.y;
    double distance = sqrt(dx * dx + dy * dy);

    // do not intersects
    if (distance > r1 + r2 || distance < fabs(r1 - r2)) {
        return false;
    }

    //direction vector divation
    double a = (r1 * r1 - r2 * r2 + distance * distance);
    double h = sqrt(r1 * r1 - a * a);

    //midpoint
    double m_x = C1.x + a * (dx / distance);
    double m_y = C1.y + a * (dy / distance);

    //insection coordinates p q
    double p_x = m_x + h * (dy / distance);
    double p_y = m_y - h * (dx / distance);
    double q_x = m_x - h * (dy / distance);
    double q_y = m_y + h * (dx / distance);


    intersections.push_back({ p_x,p_y });
    if (distance != r1 + r2) {
        intersections.push_back({ q_x,q_y });
    }

    return true;
}

bool Arc::FindArcIntersections(Arc& arc1, Arc& arc2, std::vector<Point>& intersections) {

    std::vector<Point> circleintersections;
    if (!CirclesArcIntersect(arc1.center, arc1.radius, arc2.center, arc2.radius, circleintersections)) {
        return false;
    }

    for (const Point& p : circleintersections) {
        if (arc1.IsPointInArc(p) && arc2.IsPointInArc(p)) {
            intersections.push_back(p);
        }
    }

    return !intersections.empty();
}





